#coding:utf-8
"""
 @authr: Loopher
 @date:2020/07/28 
 @description:  rpc调用脚本构建
"""
import codecs
import os

# from  houseUtil import render

class RpcScriptBuilder(object):


    def __new__(cls):
        if not hasattr(cls,"instance"):
            cls.instance = super(RpcScriptBuilder,cls).__new__(cls)
            cls.instance.__init()
        return cls.instance

    def __init(self):
        
        self.rpc_call_model = "./scripts/rpc/rpc_call.js"
        self.rpc_call_env = "./scripts/enum/env_rpc.js" #  evn 
        
        self.rpc_call_hook  = './scripts/hook/hook_tpl_rpc.js'
        self.rpc_call_hook_mini = "./scripts/hook/hook_tpl_mini_rpc.js"
        
        self.rpc_call_monitor_path = "./scripts/monitor/monitor_tpl_rpc.js"

        self.rpc_call_enum_class_info = "./scripts/enum/enum_skl_rpc.js" #  

        self.rpc_call_inspect = "./scripts/intercept/inspect_rpc.js"
        self.rpc_call_intercept_rpc = "./scripts/intercept/intercept_rpc.js"

        self.rpc_call_sideload_stetho = "./scripts/misc/sideload_stetho_rpc.js"
        self.rpc_call_preload = "./scripts/misc/preload_rpc.js"  
        
    def build_rpc_env(self,render_fn,info):
        # 接收render函数和info对象，用来构建第一个script后面得自己构建rpc模式
        result =  ""
        script = render_fn(self.rpc_call_env,info)
        result = render_fn(self.rpc_call_model,{"rpc_procedure":script,"call_rpc_name":"call_env();"})
        return result

    def build_rpc_monitor(self,render_fn,context):
        
        script = render_fn(self.rpc_call_monitor_path,context)
        result = render_fn(self.rpc_call_model,{"rpc_procedure":script,"call_rpc_name":"call_monitor();"})
        return result


    def build_rpc_enum_class(self,render_fn,context):
        # 枚举类信息
        script = render_fn(self.rpc_call_enum_class_info,context)
        result = render_fn(self.rpc_call_model,{"rpc_procedure":script,"call_rpc_name":"call_enum_class_info();"})
        return result

    def build_rpc_hook(self,render_fn,hook_script_codes,is_mini=False):
        """
        :param  render_fn: 脚本渲染函数
        :param hook_script_codes: hook的代码片段信息 可能是多个组合而成的字符串 
         {'scripts': basicscript, 'native_scripts': nativescript, "dyloadscript": dyloadscript}
        """
        # hook方法脚本
        call_name="call_hook();"
        if is_mini is False:
            script = render_fn(self.rpc_call_hook,hook_script_codes)
        else:
            script = render_fn(self.rpc_call_hook_mini,hook_script_codes)
            call_name = "call_hook_mini();"
        # 构建rpc模式调用
        return render_fn(self.rpc_call_model,{"rpc_procedure":script,"call_rpc_name":call_name})

    def build_rpc_inspect(self,render_fn,context):
        """
        :param render_fn  render js code
        :param context  需要再次渲染的程序 dict 
        """
        script = render_fn(self.rpc_call_inspect,context)
        result = render_fn(self.rpc_call_model,{"rpc_procedure":script,"call_rpc_name":"call_inspect_rpc();"})
        return result


    def build_rpc_interceptor(self,render_fn,context):
        """
        :param render_fn  render js code
        :param context  需要再次渲染的程序 dict 
        """
        script = render_fn(self.rpc_call_intercept_rpc,context)
        result = render_fn(self.rpc_call_model,{"rpc_procedure":script,"call_rpc_name":"call_intercept_rpc();"})
        return result

    
    def build_rpc_sideload_stetho(self,render_fn,context):
        """
        sideload stetho mode
        """
        script = render_fn(self.rpc_call_sideload_stetho,context)
        result = render_fn(self.rpc_call_model,{"rpc_procedure":script,"call_rpc_name":"call_sideload_stetho_rpc();"})
        return result

    def build_rpc_preload(self,render_fn,context):
        """
        preload 
        """
        script = render_fn(self.rpc_call_preload,context)
        result = render_fn(self.rpc_call_model,{"rpc_procedure":script,"call_rpc_name":"preload_rpc();"})
        return result


    def check_env(self):
        if not os.path.isfile(self.rpc_call_model):
            print(" ---> not file",self.rpc_call_model)
        if not os.path.isfile(self.rpc_call_script):
            print(" --> not file  ",self.rpc_call_script)

        data = codecs.open(self.rpc_call_script,'r',encoding="utf-8").read()
        with codecs.open(self.rpc_call_model,"r", encoding="utf-8") as fp:
            content = fp.read()
            a=content.replace("#rpc_procedure",data)
            print(a)

if __name__ =='__main__':

    RpcScriptBuilder().check_env()